package com.skycity.auth.authentication.convert;

import com.skycity.auth.authentication.OAuth2PasswordAuthenticationToken;
import com.skycity.auth.constants.SecurityConstants;
import com.skycity.auth.utils.SecurityUtils;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
import org.springframework.security.web.authentication.AuthenticationConverter;
import org.springframework.util.MultiValueMap;

import java.util.HashMap;
import java.util.Map;

/**
 * @Description
 * @Author YingBo.Dai
 * @Date 2024/9/26
 * @Version 1.0
 */
@Slf4j
public class OAuth2PasswordAuthenticationConverter implements AuthenticationConverter {
    @Override
    public Authentication convert(HttpServletRequest request) {
        String grantType = request.getParameter(OAuth2ParameterNames.GRANT_TYPE);
        if (!SecurityConstants.PASSWORD.getValue().equals(grantType)) {
            return null;
        }else {
            Authentication clientPrincipal = SecurityContextHolder.getContext().getAuthentication();
            MultiValueMap<String, String> parameters = SecurityUtils.getParameters(request);

            String username = SecurityUtils.checkRequiredParameter(parameters,OAuth2ParameterNames.USERNAME);
            String password = SecurityUtils.checkRequiredParameter(parameters,OAuth2ParameterNames.PASSWORD);

            Map<String,Object> additionalParameters = new HashMap<>();
            parameters.forEach((key, value) -> {
                if (!key.equals(OAuth2ParameterNames.GRANT_TYPE) &&
                        !key.equals(OAuth2ParameterNames.USERNAME) &&
                        !key.equals(OAuth2ParameterNames.PASSWORD)) {
                    additionalParameters.put(key, value.get(0));
                }
            });
            return new OAuth2PasswordAuthenticationToken(username, password, clientPrincipal, additionalParameters);
        }
    }
}
